package org.builder.web.validator;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.builder.bean.validator.Field;
import org.builder.bean.validator.Task;
import org.builder.bean.validator.Validator;
import org.builder.io.Resolver;
import org.builder.service.UnmarshallService;

public class DefaultTaskValidator implements TaskValidator {

	private String xmlLocation = null;

	private UnmarshallService unmarshallService;

	public boolean check(Object task, Map errors) {
		Map<String, List<String>> mapDepends = new HashMap<String, List<String>>();
		Map<String, Object> mapTaskValues = new HashMap<String, Object>();
		try {
			if (xmlLocation == null) {
				setXmlLocation("classpath:/validator-tasks.xml");
			}
			InputStream inStream = Resolver.resolveFileLocation(xmlLocation);
			Validator validator = (Validator) unmarshallService
					.unmarshall(inStream,Validator.class);
			Task xmlTask = null;
			List<Task> tasks = validator.getTasks();
			for (Iterator<Task> iter = tasks.iterator(); iter.hasNext();) {
				Task t = iter.next();
				String className = t.getClassName();
				if (className.equalsIgnoreCase(task.getClass().getName())) {
					xmlTask = t;
					break;
				}
			}
			if (xmlTask == null) {
				// TODO exception
				throw new Exception();
			}
			List<Field> fields = xmlTask.getFields();
			for (Iterator<Field> iter = fields.iterator(); iter.hasNext();) {
				Field field = iter.next();
				String name = field.getName();
				String required = field.getRequired();
				String methodName = "get" + StringUtils.capitalize(name);
				Method m = Resolver.resolveMethodName(task, methodName, null);
				Object value = m.invoke(task, (Object[]) null);
				if((value==null || value.equals("")) && (required != null && required.equalsIgnoreCase("true"))){
					errors.put(name, "Campo obbligatorio");
				}
				mapTaskValues.put(name, value);
				List<String> depends = field.getDepends();
				for (Iterator<String> iterator = depends.iterator(); iterator
						.hasNext();) {
					String depend = iterator.next();
					if (!depend.trim().equals("")) {
						List<String> tmp = mapDepends.get(name);
						if (tmp == null) {
							tmp = new ArrayList<String>();
						}
						tmp.add(depend);
						mapDepends.put(name, tmp);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		Iterator<String> it = mapTaskValues.keySet().iterator();
		while (it.hasNext()) {
			String fieldName = it.next();
			Object obj = mapTaskValues.get(fieldName);
			if (obj == null || obj.equals("")) {
				checkDependence(errors, mapDepends, mapTaskValues, fieldName,obj);
			}

		}
		System.out
				.println("************************************************************+");
		System.out.println(mapDepends);
		System.out.println(mapTaskValues);
		System.out
				.println("************************************************************+");
		return errors.size() == 0;
	}

	private void checkDependence(Map errors,
			Map<String, List<String>> mapDepends,
			Map<String, Object> mapTaskValues, String fieldName,Object obj) {
		List<String> depends = mapDepends.get(fieldName);
		if (depends != null) {
			for (int i = 0; i < depends.size(); i++) {
				String field = (String) depends.get(i);
				Object parent = mapTaskValues.get(field);
				if ((obj == null || obj.equals("")) && !parent.equals("")) {
					errors.put(fieldName,"Campo obbligatorio");
				}
			}
		}
	}

	public String getXmlLocation() {
		return xmlLocation;
	}

	public void setXmlLocation(String xmlLocation) {
		this.xmlLocation = xmlLocation;
	}

	public void setUnmarshallService(UnmarshallService unmarshallService) {
		this.unmarshallService = unmarshallService;
	}

}
